package com.cy.game

import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.core.view.marginBottom
import androidx.fragment.app.viewModels
import com.business.Analyse
import com.business.AnalyseKey
import com.helloandroid.AppUtil
import com.helloandroid.R
import com.helloandroid.ads.VideoAdUtil
import com.helloandroid.app.model.AppCache
import com.helloandroid.base.BaseFragment
import com.helloandroid.tools.NetWorkUtil
import dai.ui.UITweenModel
import org.json.JSONArray
import java.lang.RuntimeException

class CyGameFragment : BaseFragment() {

    companion object{
        const val kContentPadding = 30f
    }

    lateinit var lstSelRegionLinearLayout: List<LinearLayout>
    lateinit var ivCur: ImageView
    lateinit var flLayout: RelativeLayout
    lateinit var tvLevel: TextView
    lateinit var tvHint: TextView
    lateinit var rlTipLayout:RelativeLayout
    val tweenModel: UITweenModel by viewModels()

    var board: Board = Board(this)
    var scale = 1.0f

    var lstViews = ArrayList<ArrayList<FrameLayout>>()

    lateinit var cyAct: CyHomeActivity
    override fun onAttach(context: Context) {
        super.onAttach(context)
        cyAct = context as CyHomeActivity
    }

    override fun getLayoutResId(): Int = R.layout.fragment_cy_game

    override fun initView(view: View) {
        val info = cyAct.mInfo!!
        tweenModel.startLoop()
        flLayout = findViewById(R.id.flcontent)
        ivCur = findViewById(R.id.ivCur)
        tvLevel = findViewById(R.id.tvLevel)
        tvLevel.text = "第${info.curLevel}关"
        tvHint = findViewById(R.id.tvHint)
        rlTipLayout = findViewById(R.id.midContainer)
        updateTipUI(info)

        // back
        findBtn(R.id.btnBack).setOnClickListener { cyAct.navToCyHome() }

        scale = resources.displayMetrics.widthPixels / 1080f
        val realSide = (Board.SideW * scale).toInt()
        val paddingTop = (-3 * scale).toInt()
                // resources.getDimension(R.dimen.dp2)

        for (i in 0 until Board.ContentRow) {
            val views = ArrayList<FrameLayout>()
            for (j in 0 until Board.ContentColumn) {
                val frameLayout = FrameLayout(requireContext())
                frameLayout.layoutParams = ViewGroup.LayoutParams(
                        realSide,
                        realSide
                )
                frameLayout.x = board.calContentX(j) * scale
                frameLayout.y = board.calContentY(i) * scale + kContentPadding * scale
                frameLayout.setBackgroundResource(R.drawable.yh_worddi)

                val textView = TextView(requireContext())
                textView.setTextColor(Color.BLACK)
                textView.typeface = AppCache.getMsYaHeiTypeface()
                textView.setTextSize(TypedValue.COMPLEX_UNIT_SP,26f)
                textView.setTypeface(null, Typeface.BOLD)
                textView.gravity = Gravity.CENTER_HORIZONTAL
                val params = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                )
                // params.setMargins(0,0,0,marginBottom)
                textView.layoutParams = params
                textView.setPadding(0,paddingTop,0,0)
                frameLayout.addView(textView)
                flLayout.addView(frameLayout)
                views.add(frameLayout)
            }
            lstViews.add(views)

            val height = Board.SideH * Board.ContentRow + Board.GapH * (Board.ContentRow - 1) + kContentPadding * 2
            flLayout.layoutParams.width = resources.displayMetrics.widthPixels
            flLayout.layoutParams.height = (height * scale).toInt()
        }

        lstSelRegionLinearLayout = intArrayOf(
                R.id.selRow0,
                R.id.selRow1,
                R.id.selRow2).map { findViewById<LinearLayout>(it) }

        // 提示
        findBtn(R.id.midContainer).setOnClickListener {
            hint()
        }
    }

    override fun initData() {
        val info = cyAct.mInfo!!
        cyAct.model.loadLevel(info.curLevel) { jsonArray ->
            // isReady
            initGameData(jsonArray)
        }
    }

    private fun hint() {

        if (board.checkWin()) {
            // 已经过关,还提示个毛线
            return
        }

        // 剩余次数是否够
        val info = cyAct.mInfo!!
        if (info.tipCount < 1){
            // 播放广告
            VideoAdUtil.playVideoAd(cyAct){success->
                if (success){
                    Analyse.report(AnalyseKey.Cy_Hint_Video)
                    AppUtil.appViewModel().cyHint()
                    realHint()
                }else{
                    AppUtil.toast("视频广告还没准备好!")
                }
            }
        }else{
            info.tipCount--
            updateTipUI(info)
            realHint()
        }
    }

    private fun updateTipUI(info:CyInfo){
        if (info.tipCount > 0){
            tvHint.text = "${info.tipCount}"
            rlTipLayout.setBackgroundResource(R.drawable.yh_tishi)
        }else{
            tvHint.text = ""
            rlTipLayout.setBackgroundResource(R.drawable.yh_tishi_ad)
        }
    }

    private fun realHint(){
        // 1. 找出所有要填的格子
        // 2. 找出这些格子相关的成语
        // 3. 进行提示就OK了
        val curItem = board.curItem
        val lstItems = ArrayList<Item>()
        findItems(curItem, lstItems)

        // 填充lstItems,并且里面不为空的要下来
        val downLst = ArrayList<String>()
        lstItems.forEach { item ->
            if (item.value != "") {
                downLst.add(item.value)
            }
        }

        //
        val upLst = ArrayList<String>()  //
        lstItems.forEach { item ->
            item.value = board.winTable[item.getComposeIdx()].toString()
            item.textView!!.text = item.value
            item.state = ItemState.ContentFillBg
            upLst.add(item.value)
        }

        // 找到所有完成的成语
        val proverbSet = LinkedHashSet<Proverb>()
        lstItems.forEach { item ->
            val ps = board.findRelatedProverbs(item)
            ps.forEach { p ->
                if (p.isRightFill(board)) {
                    proverbSet.add(p)
                }
            }
        }

        // 先下来,再上去
        downLst.forEach { v ->
            val selItem = board.findFirstEmptySelItem()
            selItem.value = v
            selItem.textView!!.text = v
            selItem.state = ItemState.DefaultSelRegionBg
            selItem.frameLayout!!.isClickable = true
        }

        //
        upLst.forEach { v ->
            var tmpSelItem = board.findSelItemByValue(v)
            if (tmpSelItem == null) {
                // upLst 里面的字 可能不在 selRegion 里面
                // 从 content 里错误的地方找到该字,然后直接拿下来
                val errorItem = board.findErrorItem(v)
                errorItem.putWordDown()
            }
            tmpSelItem = board.findSelItemByValue(v)
            val selItem = tmpSelItem!!
            selItem.value = ""
            selItem.textView!!.text = ""
            selItem.state = ItemState.InvalidBg
            selItem.frameLayout!!.isClickable = false
        }

        // 播放动画
        val hitProverbSize = proverbSet.size
        proverbSet.forEachIndexed { index, proverb ->
            proverb.playRightAnim(board, index * 0.4f)
        }

        if (board.checkWin()) {
            // 游戏过关
            cyAct.model.delayRun(hitProverbSize * 0.5f) {
                showWinDialog()
            }
        } else {
            // 更新curItem
            updateCurItem(curItem)
        }
    }

    private fun initGameData(jsonArray: JSONArray) {
        board.initLevel(jsonArray)
    }

    fun getCurItem() = board.curItem

    fun setCurItem(newItem: Item) {
        board.curItem = newItem
        ivCur.x = newItem.frameLayout!!.x
        ivCur.y = newItem.frameLayout!!.y
    }

    /**
     *  pre: 关卡还没过关
     */
    private fun nextItem(item: Item): Item {
        // 找到他附近的一个位置
        // 1. 一行的有没有
        // 2. 一列的有没有

        // 1. 找到这个位置的单词
        val maybeProverbs = board.findRelatedProverbs(item)
        if (maybeProverbs.isEmpty()) {
            throw RuntimeException("maybeProverbs size < 1.  error!")
        }

        if (maybeProverbs.size > 1) {
            // 属于2个  一个位置最多只能属于2个位置
            //
            val p0 = maybeProverbs[0]
            val p1 = maybeProverbs[1]
            val p0_fill_count = p0.fillCount(board)
            val p1_fill_count = p1.fillCount(board)

            if (p0_fill_count >= 4 && p1_fill_count >= 4) {
                // 附近选一个
                // return p0.findEmptyItem(board)
                // 找到一个空成语
                return board.findNextItem()
            } else {
                if (p0_fill_count >= 4) {
                    // 第一个填满了
                    val pos = p1.findFirstEmptyPos(board)
                    return board.lstContent[pos.first][pos.second]
                } else if (p1_fill_count >= 4) {
                    // 第2个填满了
                    val pos = p0.findFirstEmptyPos(board)
                    return board.lstContent[pos.first][pos.second]
                } else {
                    // 都没填满
                    if (p0_fill_count >= p1_fill_count) {
                        val pos = p0.findFirstEmptyPos(board)
                        return board.lstContent[pos.first][pos.second]
                    } else {
                        val pos = p1.findFirstEmptyPos(board)
                        return board.lstContent[pos.first][pos.second]
                    }
                }
            }
        } else {
            val proverb = maybeProverbs[0]
            // 属于单个,判断所在单词是否填满
            if (proverb.isFill(board)) {
                // 找到一个空成语
                return board.findNextItem()
            } else {
                // 找到第一个空位置
                val pos = proverb.findFirstEmptyPos(board)
                return board.lstContent[pos.first][pos.second]
            }
        }
    }

    fun showWinDialog() {
        // 过关
        if (!NetWorkUtil.networkConnected()) {
            AppUtil.toast("请打开网络!")
            return
        }
        WinDialog(cyAct,this).show()
    }

//    fun gotoNextLevel() {
//        // 判断是否是最后一关
//        val info = cyAct.mInfo!!
//        if (info.curLevel > info.totalLevel) {
//            AppUtil.toast("已经通关所有关卡！后续关卡敬请期待！")
//            cyAct.navToCyHome()
//            return
//        }
//
//        cyAct.realStartGame(info)
//    }

    //  item位置可能有字,但是是错的
    private fun findItems(item: Item, lstItems: ArrayList<Item>) {
        lstItems.add(item);

        // 判断填入这个格子后,是否还需要继续填
        // 模拟填入 item
        val oldFirstItemValue = item.value
        item.value = board.winTable[item.getComposeIdx()].toString()
        val maybeProverbs = board.findRelatedProverbs(item)
        val p = maybeProverbs.find { p ->
            p.isRightFill(board)
        }
        if (p == null) {

            val p0 = maybeProverbs[0]

            // 里面的错误格子或者空格子
            p0.findEmptyOrWrongItem(board, lstItems)

            // 恢复第一个
            item.value = oldFirstItemValue
        } else {
            // 恢复第一个
            item.value = oldFirstItemValue
        }
    }

    fun updateCurItem(curItem: Item) {
        if (!board.isFullFill()) {
            //  移动到下一个位置
            val newNextItem = nextItem(curItem)
            setCurItem(newNextItem)
        } else {
            // 可能有两个成语里面,正好两个字不一样
            // 找到错误一个item,移动到此位置
            val newNextItem = board.findFirstErrorItem()
            setCurItem(newNextItem)
        }
    }



}